﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using NHibernate;
using TeamCommunitySolution.Services.Factories;
using TeamCommunitySolution.Domain.DataLayer.Base;
using System.Data.SqlClient;

namespace TeamCommunitySolution.Services.Repositories.Impl
{
    /// <summary>
    /// Implementation of the IMessage Repository Interface against nhibernate
    /// </summary>
    public class MessageRepository : IMessageRepository
    {

        /// <summary>
        /// The log instance.
        /// </summary>
        private static readonly ILog _log = LogManager.GetLogger(typeof(MessageRepository));

        /// <summary>
        /// The repository instance
        /// </summary>
        private static IMessageRepository _repo = null;

        /// <summary>
        /// Prevents a default instance of the <see cref="MessageRepository"/> class from being created.
        /// </summary>
        private MessageRepository()
        {
        }

        /// <summary>
        /// Gets the instance of the repository Instance.
        /// </summary>
        public static IMessageRepository Instance
        {
            get
            {
                if (_repo == null)
                {
                    _repo = new MessageRepository();
                }

                return _repo;
            }
        }

        #region IMessageRepository Members

        /// <summary>
        /// Deletes the inbox message.
        /// </summary>
        /// <param name="messageId">The message id.</param>
        public void DeleteInboxMessage(string messageId)
        {
            using (ISession session = NHSessionFactory.Factory.OpenSession())
            {
                var scope = session.BeginTransaction();
                try
                {
                    MessageInbox message = this.GetInboxMessage(messageId);
                    session.Delete(message);
                    scope.Commit();
                }
                catch (SqlException ex)
                {
                    scope.Rollback();
                    string message = "Could not delete the object [MessageInbox] from the datastore";
                    this.HandleException(message, ex);
                }
            }
        }

        /// <summary>
        /// Deletes the outbox message.
        /// </summary>
        /// <param name="messageId">The message id.</param>
        public void DeleteOutboxMessage(string messageId)
        {
            using (ISession session = NHSessionFactory.Factory.OpenSession())
            {
                var scope = session.BeginTransaction();
                try
                {
                    MessageOutbox message = this.GetOutboxMessage(messageId);
                    session.Delete(message);
                    scope.Commit();
                }
                catch (SqlException ex)
                {
                    scope.Rollback();
                    string message = "Could not delete the object [MessageOutbox] from the datastore";
                    this.HandleException(message, ex);
                }
            }
        }

        public void CreateMessage(MessageInbox messageIn, MessageOutbox messageOut) {
          using(ISession session = NHSessionFactory.Factory.OpenSession()) {
            var scope = session.BeginTransaction();
            try {
              session.SaveOrUpdateCopy(messageIn);
              session.SaveOrUpdateCopy(messageOut);
              scope.Commit();
            } catch(SqlException ex) {
              scope.Rollback();
              string message = "Could not delete the object [MessageOutbox] from the datastore";
              this.HandleException(message, ex);
            }
          }
        }

        /// <summary>
        /// Gets the outbox message.
        /// </summary>
        /// <param name="messageId">The message id.</param>
        /// <returns>The Message Outbox instance.</returns>
        public MessageOutbox GetOutboxMessage(string messageId)
        {
            using (ISession session = NHSessionFactory.Factory.OpenSession())
            {
                try
                {
                    return session.Get<MessageOutbox>(messageId);
                }
                catch (SqlException ex)
                {
                    string message = "Could not find the object [MessageOutbox] in the datastore";
                    this.HandleException(message, ex);
                }

                return null;
            }
        }

        /// <summary>
        /// Gets the inbox message.
        /// </summary>
        /// <param name="messageId">The message id.</param>
        /// <returns>The Message Inbox instance.</returns>
        public MessageInbox GetInboxMessage(string messageId)
        {
            using (ISession session = NHSessionFactory.Factory.OpenSession())
            {
                try
                {
                    return session.Get<MessageInbox>(messageId);
                }
                catch (SqlException ex)
                {
                    string message = "Could not find the object [MessageInbox] in the datastore";
                    this.HandleException(message, ex);
                }

                return null;
            }
        }

        #endregion

        /// <summary>
        /// Handles the exception.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ex">The ex.</param>
        private void HandleException(string message, Exception ex)
        {
            _log.Error(message, ex);
            throw new MessageRepositoryException(message, ex);
        }
    }
}
